package com.ruoyi.student.controller;

import java.io.IOException;
import java.lang.reflect.Field;
import java.time.LocalDate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;

import com.ruoyi.common.annotation.Excel;
import com.ruoyi.common.core.domain.model.LoginUser;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.uuid.IdUtils;
import com.ruoyi.common.utils.uuid.UUID;
import com.ruoyi.student.domain.vo.*;
import com.ruoyi.student.service.ICourseSchedulingIinquiryService;
import com.ruoyi.student.service.StudentTutorImportService;
import com.ruoyi.student.service.impl.StudentInfoServiceImpl;
import com.ruoyi.teacher.domain.teacher;
import com.ruoyi.teacher.service.IteacherService;
import com.ruoyi.trainingManagement.domain.CourseScheduleDetails;
import com.ruoyi.trainingManagement.domain.CourseStudentInfo;
import com.ruoyi.trainingManagement.domain.TrainingProgramCoursesSchedule;
import com.ruoyi.trainingManagement.domain.trainingProgram;
import com.ruoyi.trainingManagement.service.*;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import com.ruoyi.common.annotation.Log;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.enums.BusinessType;
import com.ruoyi.student.domain.StudentInfo;
import com.ruoyi.student.service.IStudentInfoService;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.common.core.page.TableDataInfo;
// 导入新增的Service
import com.ruoyi.student.service.IStudentShowJudgmentService;
import org.springframework.web.multipart.MultipartFile;

/**
 * 学生信息管理Controller
 *
 * @author gdslovehy
 * @date 2025-04-24
 */
@RestController
@RequestMapping("/student/studentManger")
public class StudentInfoController extends BaseController
{
    // 注入字段权限Service
    @Autowired
    private IStudentShowJudgmentService studentShowJudgmentService;
    @Autowired
    private IStudentInfoService studentInfoService;
    @Autowired
    private ICourseScheduleDetailsService courseScheduleDetailsService;
    @Autowired
    private ItrainingProgramService trainingProgramService;
    @Autowired
    private ICourseStudentInfoService courseStudentInfoService;
    @Autowired
    private ItrainingProgramCoursesService trainingProgramCoursesService;
    @Autowired
    private ITrainingProgramCoursesScheduleService trainingProgramCoursesScheduleService;
    @Autowired
    private StudentTutorImportService studentTutorImportService;
    @Autowired
    private ICourseSchedulingIinquiryService courseSchedulingIinquiryService;
    @Autowired
    private StudentInfoServiceImpl studentInfoServiceImpl;
    /**
     * 查询学生信息管理列表查询
     */
//    @PreAuthorize("@ss.hasPermi('student:studentManger:list')")
    @GetMapping("/list")
    public TableDataInfo list(StudentInfo studentInfo)
    {
        startPage();
        List<StudentInfo> list = studentInfoService.selectStudentInfoList(studentInfo);
        return getDataTable(list);
    }

    /**
     * 导出学生信息管理列表
     */
/*    @PreAuthorize("@ss.hasPermi('student:studentManger:export')")*/
    @Log(title = "学生信息管理", businessType = BusinessType.EXPORT)
    @PostMapping("/export")
    public void export(HttpServletResponse response, StudentInfo studentInfo)
    {
        List<StudentInfo> list = studentInfoService.selectStudentInfoList(studentInfo);
        ExcelUtil<StudentInfo> util = new ExcelUtil<StudentInfo>(StudentInfo.class);
        util.exportExcel(response, list, "学生信息管理数据");
    }

    /**
     * 获取学生信息管理详细信息
     */
    //@PreAuthorize("@ss.hasPermi('student:studentManger:query')")
    @GetMapping(value = "/{id}")
    public AjaxResult getInfo(@PathVariable("id") String id)
    {
        //打印查询到的数据studentInfoService.selectStudentInfoById(id)
        System.out.println(studentInfoService.selectStudentInfoById(id));
        return success(studentInfoService.selectStudentInfoById(id));
    }

    /**
     * 新增学生信息管理
     */
/*    @PreAuthorize("@ss.hasPermi('student:studentManger:add')")*/
    @Log(title = "学生信息管理", businessType = BusinessType.INSERT)
    @PostMapping
    public AjaxResult add(@RequestBody StudentInfo studentInfo)
    {
        studentInfo.setId(IdUtils.fastSimpleUUID());
        return toAjax(studentInfoService.insertStudentInfo(studentInfo));
    }

    /**
     * 新增：获取学生字段权限配置（供前端控制输入框禁用）
     */
    @GetMapping("/fieldPermissions")
    public AjaxResult getFieldPermissions() {
        try {
            // 返回所有字段权限（key=字段编码，value=是否可修改）
            return success(studentShowJudgmentService.getAllFieldPermissions());
        } catch (Exception e) {
            logger.error("获取字段权限失败", e);
            return AjaxResult.error("获取字段权限失败：" + e.getMessage());
        }
    }
    /**
     * 修改：学生信息管理（添加学号/姓名不可修改校验）
     */
/*    @PreAuthorize("@ss.hasPermi('student:studentManger:edit')")*/
    @Log(title = "学生信息管理", businessType = BusinessType.UPDATE)
    @PutMapping
    public AjaxResult edit(@RequestBody StudentInfo studentInfo) {
        // 1. 打印获取到的数据
        System.out.println("获取到的数据" + studentInfo);

        // 2. 权限校验：禁止修改学号（studentId）和姓名（studentName）
        // 2.1 校验学号是否被修改
        if (studentInfo.getStudentId() != null) {
            // 查询数据库中的原始学号
            StudentInfo originalStudent = studentInfoService.selectStudentInfoById(studentInfo.getId());
            if (!studentInfo.getStudentId().equals(originalStudent.getStudentId())) {
                return AjaxResult.error("学号不可修改！");
            }
        }

        // 2.2 校验姓名是否被修改
        if (studentInfo.getStudentName() != null) {
            StudentInfo originalStudent = studentInfoService.selectStudentInfoById(studentInfo.getId());
            if (!studentInfo.getStudentName().equals(originalStudent.getStudentName())) {
                return AjaxResult.error("姓名不可修改！");
            }
        }

        // 3. 调用Service更新（原有逻辑）
        return toAjax(studentInfoService.updateStudentInfo(studentInfo));
    }

    /**
     * 删除学生信息管理
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:remove')")
    @Log(title = "学生信息管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/{ids}")
    public AjaxResult remove(@PathVariable String[] ids)
    {
        return toAjax(studentInfoService.deleteStudentInfoByIds(ids));
    }
    /**
     * 通过专业ID、学期查询学生信息列表
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:list')")
    @GetMapping("/listByStudentZy/{student_zy}/{student_nj}")
    public TableDataInfo listByStudentYx(@PathVariable String student_zy, @PathVariable String student_nj) {
        System.out.println("进入方法: listByStudentYx");
        System.out.println("参数 student_zy: " + student_zy);
        System.out.println("参数 student_nj: " + student_nj);
        List<StudentInfo> list = studentInfoService.selectStudentInfoListByZyAndNj(student_zy, student_nj);
        System.out.println("查询结果: " + list);
        System.out.println("查询结果大小: " + list.size());
        return getDataTable(list);
    }
    /**
     * 批量分配培养方案给学生
     */
    //@PreAuthorize("@ss.hasPermi('student:studentManger:assignTraining')")
    @Log(title = "学生信息管理", businessType = BusinessType.UPDATE)
    @PostMapping("/assignTraining")
    public AjaxResult assignTraining(@RequestBody Map<String, Object> params) {
        System.out.println("进入方法: assignTraining"+ params);
        try {
            // 提取参数（改为String类型接收）
            String trainingProgramId = (String) params.get("trainingProgramId");
            List<String> studentIds = (List<String>) params.get("studentIds");

            System.out.println("培养方案ID: " + trainingProgramId);
            System.out.println("学生名单: " + studentIds);

            // 调用服务层方法（修改方法参数类型）
            int updatedCount = studentInfoService.assignTrainingToStudents(trainingProgramId, studentIds);
            int totalCount = studentIds.size();
            System.out.println("培养方案对应总人数"+totalCount);
            trainingProgramService.updateTrainingProgramAmount(trainingProgramId, totalCount);
            return AjaxResult.success("成功为 " + updatedCount + " 名学生分配培养方案");
        } catch (NullPointerException e) {
            return AjaxResult.error("参数不能为空");
        } catch (ClassCastException e) {
            return AjaxResult.error("参数格式错误");
        } catch (Exception e) {
            return AjaxResult.error("分配失败: " + e.getMessage());
        }
    }
    /*
     * 传入多个学生id以及一个行政班id，批量将学生分配到该行政班，讲行政班ID添加到学生信息表中
     *
     * */
    @PreAuthorize("@ss.hasPermi('student:studentManger:assignClass')")
    @Log(title = "学生信息管理", businessType = BusinessType.UPDATE)
    @PostMapping("/assignClass")
    public AjaxResult assignClass(@RequestBody Map<String, Object> params) {
        //打印接收到的参数
        System.out.println("接收到的参数：" + params);
        try {
            if (params.get("adminClassId") == null || !(params.get("adminClassId") instanceof String)) {
                return AjaxResult.error("行政班ID不能为空且必须为字符串");
            }
            if (params.get("studentIds") == null || !(params.get("studentIds") instanceof List)) {
                return AjaxResult.error("学生ID列表不能为空且必须为数组");
            }

            String adminClassId = (String) params.get("adminClassId");
            List<String> studentIds = (List<String>) params.get("studentIds");

            studentInfoService.assignStudentsToClass(adminClassId, studentIds);
            return AjaxResult.success("分配成功");
        } catch (Exception e) {
            return AjaxResult.error("分配失败: " + e.getMessage());
        }
    }
    /**
     * 手动排课接口：接收班级信息及学生名单，创建班级并关联学生
     */
    @PreAuthorize("@ss.hasPermi('trainingManagement:programPourses:saveManualClassDivision')")
    @Log(title = "手动排课", businessType = BusinessType.INSERT)
    @PostMapping("/saveManualClassDivision")
    public AjaxResult saveManualClassDivision(
            @Validated @RequestBody ManualClassDivisionRequest request,
            BindingResult bindingResult) {

        // 1. 参数校验（基于DTO的JSR303注解）
        if (bindingResult.hasErrors()) {
            String errorMsg = bindingResult.getAllErrors().stream()
                    .map(error -> error.getDefaultMessage())
                    .collect(Collectors.joining("；"));
            System.out.println("参数校验失败：" + errorMsg);
            return AjaxResult.error("参数错误：" + errorMsg);
        }

        List<ManualClassInputDTO> classList = request.getClasses();
        List<ManualClassDivisionRequest.TrainingProgramParam> trainingProgramParams = request.getTrainingPrograms();

        // 2. 基础业务校验
        if (classList.isEmpty()) {
            System.out.println("班级列表为空");
            return AjaxResult.error("班级列表不能为空");
        }

        // 校验所有班级属于同一课程
        String courseId = classList.get(0).getCourseId();
        boolean isSameCourse = classList.stream()
                .allMatch(dto -> courseId.equals(dto.getCourseId()));
        if (!isSameCourse) {
            System.out.println("存在不同课程的班级，课程ID基准：" + courseId);
            return AjaxResult.error("所有班级必须属于同一课程");
        }

        if (trainingProgramParams.isEmpty()) {
            System.out.println("培养计划列表为空");
            return AjaxResult.error("培养计划列表不能为空，请检查trainingPrograms参数");
        }

        try {
            List<ClassWithStudentsVo> resultList = new ArrayList<>();

            // 3. 遍历创建班级+关联学生
            for (ManualClassInputDTO dto : classList) {
                // 3.1 构建课程班实体（直接用DTO字段，无需Map解析）
                CourseScheduleDetails detail = new CourseScheduleDetails();
                detail.setId(UUID.randomUUID().toString());
                detail.setTrainingProgramCoursesId(dto.getTrainingProgramCoursesId());
                detail.setCourseId(dto.getCourseId());
                detail.setTrainingProgramId(dto.getTrainingProgramId());
                detail.setSemester(dto.getSemester()); // 假设semester字段已同步改为Long
                detail.setGrade(dto.getGrade());       // 假设grade字段已同步改为Long
                detail.setAcademicYear(dto.getAcademicYear().intValue()); // 两边都是Long，无类型错误
                detail.setClassName(dto.getClassName());
                detail.setMaxCapacity(dto.getMaxCapacity());
                detail.setIsRequired(dto.getIsRequired() != null ? dto.getIsRequired() : 0);
                detail.setDepartment(dto.getDepartment());
                detail.setStatus(1L);
                detail.setCurrentEnrollment(0L);

                // 3.2 保存课程班
                courseScheduleDetailsService.insertCourseScheduleDetails(detail);
                System.out.println("创建班级成功：" + detail.getClassName() + "，ID：" + detail.getId());

                // 3.3 关联学生
                List<String> studentIds = dto.getStudentIds();
                List<CourseStudentInfo> currentClassStudents = new ArrayList<>();
                List<studentDetailedVo> detailedStudents = new ArrayList<>();
                List<StudentInfo> currentOriginalStudents = new ArrayList<>();

                for (String studentId : studentIds) {
                    CourseStudentInfo courseStudentInfo = new CourseStudentInfo();
                    courseStudentInfo.setId(UUID.randomUUID().toString());
                    courseStudentInfo.setCourseScheduleDetailsId(detail.getId());
                    courseStudentInfo.setStudentId(studentId);
                    courseStudentInfo.setEnrollmentStatus(1L);

                    courseStudentInfoService.insertCourseStudentInfo(courseStudentInfo);
                    currentClassStudents.add(courseStudentInfo);

                    // 获取学生详情
                    studentDetailedVo studentDetail = studentInfoService.getStudentDetailedInfo(studentId);
                    if (studentDetail != null) {
                        detailedStudents.add(studentDetail);
                    } else {
                        System.out.println("警告：未查询到学生详情，ID=" + studentId);
                    }

                    // 获取学生原始信息
                    StudentInfo originalStudent = studentInfoService.selectStudentInfoById(studentId);
                    if (originalStudent != null) {
                        currentOriginalStudents.add(originalStudent);
                    } else {
                        System.out.println("警告：未查询到原始学生信息，ID=" + studentId);
                    }
                }

                // 3.4 更新班级人数
                detail.setCurrentEnrollment((long) currentClassStudents.size());
                courseScheduleDetailsService.updateCourseScheduleDetails(detail);
                System.out.println("班级人数更新：" + detail.getClassName() + "，人数=" + currentClassStudents.size());

                // 4. 处理中间表关联
                String courseScheduleId = detail.getId();
                System.out.println("\n处理中间表：课程班ID=" + courseScheduleId);

                // 提取学生所属培养方案ID
                Set<String> programIds = currentOriginalStudents.stream()
                        .map(StudentInfo::getTrainingProgramId)
                        .filter(Objects::nonNull)
                        .collect(Collectors.toSet());

                if (programIds.isEmpty()) {
                    System.out.println("中间表跳过：无关联培养方案");
                } else {
                    List<String> tpcIds = trainingProgramCoursesService.selectIdsByProgramIdsAndCourseId(
                            new ArrayList<>(programIds), courseId);

                    if (tpcIds.isEmpty()) {
                        System.out.println("中间表跳过：无匹配培养方案课程ID");
                    } else {
                        for (String tpcId : tpcIds) {
                            TrainingProgramCoursesSchedule schedule = new TrainingProgramCoursesSchedule();
                            schedule.setId(UUID.randomUUID().toString());
                            schedule.setTrainingProgramCoursesId(tpcId);
                            schedule.setCourseScheduleDetailsId(courseScheduleId);
                            schedule.setCreatedAt(new Date());

                            int insertRes = trainingProgramCoursesScheduleService.insertTrainingProgramCoursesSchedule(schedule);
                            if (insertRes > 0) {
                                System.out.println("中间表插入成功：TPC-ID=" + tpcId + "，课程班ID=" + courseScheduleId);
                            } else {
                                System.out.println("警告：中间表插入失败：TPC-ID=" + tpcId);
                            }
                        }
                    }
                }

                // 5. 封装返回结果
                ClassWithStudentsVo resultVo = new ClassWithStudentsVo();
                resultVo.setClassInfo(detail);
                resultVo.setStudents(detailedStudents);
                resultList.add(resultVo);
            }

            // 6. 更新培养计划课程信息（核心修改：参数改为Long，无需转换）
            List<trainingProgram> programList = trainingProgramParams.stream()
                    .map(param -> {
                        trainingProgram p = new trainingProgram();
                        p.setId(param.getId());
                        return p;
                    })
                    .filter(p -> p.getId() != null)
                    .collect(Collectors.toList());

            if (programList.isEmpty()) {
                return AjaxResult.error("培养计划列表无有效ID");
            }

            // 直接传递Long类型的maxCapacity（无需转换）
            Long maxCapacity = classList.get(0).getMaxCapacity();
            int updateCount = trainingProgramCoursesService.updateByProgramAndCourseId(
                    programList,
                    courseId,
                    classList.size(),
                    Math.toIntExact(maxCapacity) // 此处改为Long类型，与方法参数对齐
            );

            if (updateCount <= 0) {
                System.out.println("警告：培养计划更新失败，影响行数=" + updateCount);
            } else {
                System.out.println("培养计划更新成功，影响行数=" + updateCount);
            }

            return AjaxResult.success("手动分班成功", resultList);

        } catch (Exception e) {
            System.out.println("手动分班失败：" + e.getMessage());
            e.printStackTrace();
            return AjaxResult.error("手动分班失败: " + e.getMessage());
        }
    }

    /**
     * 根据开班规则进行增设课程上课班级以及划分班级名单
     */
    //@PreAuthorize("@ss.hasPermi('trainingManagement:programPourses:generateClassList')")
    @Log(title = "培养计划课程明细", businessType = BusinessType.OTHER)
    @PostMapping("/generateClassList")
    public AjaxResult generateClassList(@RequestBody Map<String, Object> data) {
        System.out.println("打印获取到的参数" + data);

        // 1. 参数校验
        if (data == null) {
            return AjaxResult.error("请求数据不能为空");
        }
        if (!data.containsKey("courseInfo")) {
            return AjaxResult.error("缺少课程信息");
        }
        if (!data.containsKey("trainingPrograms") || ((List<?>) data.get("trainingPrograms")).isEmpty()) {
            return AjaxResult.error("缺少培养方案信息");
        }
        if (!data.containsKey("divisionRules")) {
            return AjaxResult.error("缺少分班规则信息");
        }

        Map<String, Object> divisionRules = (Map<String, Object>) data.get("divisionRules");
        if (!divisionRules.containsKey("numClasses") || !divisionRules.containsKey("maxClassSize")) {
            return AjaxResult.error("分班规则必须包含班级数量和最大班级人数");
        }

        try {
            // 2. 安全解析输入
            Map<String, Object> courseInfo = (Map<String, Object>) data.get("courseInfo");
            String courseId = getStringValue(courseInfo, "id"); // 课程ID
            if (courseId == null) {
                return AjaxResult.error("课程ID不能为空");
            }

            @SuppressWarnings("unchecked")
            List<Map<String, Object>> trainingProgramMaps = (List<Map<String, Object>>) data.get("trainingPrograms");
            // 转换为培养计划实体列表
            List<trainingProgram> trainingProgramList = trainingProgramMaps.stream()
                    .map(tp -> {
                        trainingProgram program = new trainingProgram();
                        program.setId(getStringValue(tp, "id")); // 设置培养方案ID
                        return program;
                    })
                    .filter(program -> program.getId() != null) // 过滤无效ID
                    .collect(Collectors.toList());

            // 分班规则参数
            Integer numClasses = getIntegerValue(divisionRules, "numClasses", 1);
            Integer maxClassSize = getIntegerValue(divisionRules, "maxClassSize", 0);
            Integer academicYear = getIntegerValue(data, "academicYear", 0);
            System.out.println("解析到的学年信息：" + academicYear); // 验证是否拿到1
            // 3. 校验分班参数
            if (numClasses <= 0) {
                return AjaxResult.error("班级数量必须大于0");
            }
            if (maxClassSize <= 0) {
                return AjaxResult.error("最大班级人数必须大于0");
            }

            // 4. 查询学生并分班（核心：保存原始学生列表用于后续信息组装）
            List<String> trainingProgramIds = trainingProgramList.stream()
                    .map(trainingProgram::getId)
                    .collect(Collectors.toList());
            List<StudentInfo> students = studentInfoService.selectStudentInfoListByTrainingProgramIds(trainingProgramIds);
            System.out.println("列表学生名单" + students);
            System.out.println("======================================");
            System.out.println("原始学生列表（共" + students.size() + "人）：");
            students.forEach(student -> {
                System.out.println("学生ID: " + student.getId() +  // 确认原始ID字段
                        ", 姓名: " + student.getStudentName());
            });
            System.out.println("======================================\n");

            if (students.isEmpty()) {
                return AjaxResult.error("未查询到学生信息，无法进行分班");
            }
            if (students.size() > numClasses * maxClassSize) {
                return AjaxResult.error("学生总人数超过最大承载量，请调整分班规则");
            }

            // 5. 计算均衡的分班人数
            int totalStudents = students.size();
            int baseCount = totalStudents / numClasses;
            int remainder = totalStudents % numClasses;
            int studentIndex = 0;

            // 关键：记录每个班级对应的原始StudentInfo列表（用于后续获取正确ID）
            Map<String, List<StudentInfo>> classOriginalStudentsMap = new HashMap<>(numClasses);
            // 保留原有的CourseStudentInfo映射（用于数据关联）
            Map<String, List<CourseStudentInfo>> classList = new HashMap<>(numClasses);

            // 6. 创建班级并分配学生
            List<CourseScheduleDetails> allCreatedClasses = new ArrayList<>();
            for (int i = 1; i <= numClasses; i++) {
                int currentClassSize = baseCount + (i <= remainder ? 1 : 0);
                currentClassSize = Math.min(currentClassSize, maxClassSize);

                // 创建班级信息
                CourseScheduleDetails detail = new CourseScheduleDetails();
                detail.setId(UUID.randomUUID().toString());
                detail.setTrainingProgramCoursesId(UUID.randomUUID().toString());

                // 设置课程信息
                if (courseInfo != null) {
                    detail.setCourseId(getStringValue(courseInfo, "id"));
                    String baseName = getStringValue(courseInfo, "courseName", "未命名课程");
                    LocalDate now = LocalDate.now();
                    String sem = now.getMonthValue() >= 9 ? "秋" : "春";
                    detail.setClassName(baseName + "-" + now.getYear() + sem + "-" + i + "班");
                    detail.setSemester(getLongValue(courseInfo, "semester", null));
                    detail.setGrade(getLongValue(courseInfo, "grade", null));
                    detail.setAcademicYear((int) academicYear.longValue());
                    System.out.println("给课程班[" + detail.getClassName() + "]设置学年：" + academicYear);
                    detail.setCourseType(getLongValue(courseInfo, "courseType", null));
                    detail.setIsRequired(getIntegerValue(courseInfo, "isRequired", 0));
                    detail.setDepartment(getStringValue(courseInfo, "applicableDepartments", ""));
                    detail.setCourseType(getLongValue(courseInfo, "courseNature", null));
                }

                // 设置培养方案信息
                @SuppressWarnings("unchecked")
                List<Map<String, Object>> trainingPrograms = (List<Map<String, Object>>) data.get("trainingPrograms");
                if (!trainingPrograms.isEmpty()) {
                    detail.setTrainingProgramId(getStringValue(trainingPrograms.get(0), "id"));
                }

                detail.setMaxCapacity(maxClassSize.longValue());
                detail.setStatus(1L);
                detail.setCurrentEnrollment(0L);
                courseScheduleDetailsService.insertCourseScheduleDetails(detail);

                allCreatedClasses.add(detail);

                // 分配学生到当前班级
                List<CourseStudentInfo> currentClassStudents = new ArrayList<>();
                List<StudentInfo> currentOriginalStudents = new ArrayList<>(); // 记录原始StudentInfo
                int enrollmentCount = 0;

                for (int j = 0; j < currentClassSize && studentIndex < students.size(); j++, studentIndex++) {
                    StudentInfo originalStudent = students.get(studentIndex); // 原始学生信息
                    CourseStudentInfo courseStudentInfo = new CourseStudentInfo();
                    courseStudentInfo.setId(UUID.randomUUID().toString());
                    courseStudentInfo.setCourseScheduleDetailsId(detail.getId());
                    courseStudentInfo.setStudentId(originalStudent.getId()); // 确保使用原始ID
                    courseStudentInfo.setEnrollmentStatus(1L);

                    courseStudentInfoService.insertCourseStudentInfo(courseStudentInfo);
                    currentClassStudents.add(courseStudentInfo);
                    currentOriginalStudents.add(originalStudent); // 存入原始学生列表
                    enrollmentCount++;
                }

                // 更新班级人数
                if (enrollmentCount > 0) {
                    detail.setCurrentEnrollment((long) enrollmentCount);
                    courseScheduleDetailsService.updateCourseScheduleDetails(detail);
                }

                // 保存映射关系
                classList.put(detail.getId(), currentClassStudents);
                classOriginalStudentsMap.put(detail.getId(), currentOriginalStudents); // 关键：保存原始学生列表
            }

            // 7. 更新培养计划课程信息
            int updateCount = trainingProgramCoursesService.updateByProgramAndCourseId(
                    trainingProgramList,
                    courseId,
                    numClasses,
                    maxClassSize
            );

            if (updateCount <= 0) {
                throw new RuntimeException("分班成功，但更新培养计划课程信息失败");
            }
            // ===================== 新增：处理中间表关联逻辑 =====================
            // 遍历所有创建的课程班，建立与培养方案课程的关联
            for (CourseScheduleDetails classDetail : allCreatedClasses) {
                String courseScheduleDetailsId = classDetail.getId(); // 课程班ID
                System.out.println("\n处理课程班ID: " + courseScheduleDetailsId + " 的中间表关联");

                // 步骤1：获取该班级的所有学生，提取不重复的培养方案ID
                List<StudentInfo> classStudents = classOriginalStudentsMap.get(courseScheduleDetailsId);
                if (classStudents == null || classStudents.isEmpty()) {
                    System.out.println("课程班ID: " + courseScheduleDetailsId + " 无学生，跳过中间表关联");
                    continue;
                }

                // 提取学生所属的培养方案ID（去重）
                Set<String> uniqueTrainingProgramIds = classStudents.stream()
                        .map(StudentInfo::getTrainingProgramId) // 假设StudentInfo有getTrainingProgramId()方法
                        .filter(Objects::nonNull) // 过滤空值（避免学生未关联培养方案）
                        .collect(Collectors.toSet());

                if (uniqueTrainingProgramIds.isEmpty()) {
                    System.out.println("课程班ID: " + courseScheduleDetailsId + " 的学生均未关联培养方案，跳过中间表关联");
                    continue;
                }
                System.out.println("课程班ID: " + courseScheduleDetailsId + " 关联的培养方案ID集合: " + uniqueTrainingProgramIds);

                // 步骤2：根据培养方案ID和课程ID，查询对应的培养方案课程ID（training_program_courses_id）
                List<String> trainingProgramCoursesIds = trainingProgramCoursesService.selectIdsByProgramIdsAndCourseId(
                        new ArrayList<>(uniqueTrainingProgramIds), // 培养方案ID列表
                        courseId // 当前课程ID
                );
                // 假设service实现：SELECT id FROM training_program_courses WHERE training_program_id IN (?) AND course_id = ?

                if (trainingProgramCoursesIds.isEmpty()) {
                    System.out.println("课程班ID: " + courseScheduleDetailsId + " 未查询到对应的培养方案课程ID，跳过中间表关联");
                    continue;
                }
                System.out.println("课程班ID: " + courseScheduleDetailsId + " 关联的培养方案课程ID集合: " + trainingProgramCoursesIds);

                // 步骤3：插入中间表（一个课程班ID对应多个培养方案课程ID）
                for (String tpcId : trainingProgramCoursesIds) {
                    TrainingProgramCoursesSchedule schedule = new TrainingProgramCoursesSchedule();
                    schedule.setId(UUID.randomUUID().toString()); // 主键
                    schedule.setTrainingProgramCoursesId(tpcId); // 培养方案课程ID
                    schedule.setCourseScheduleDetailsId(courseScheduleDetailsId); // 课程班ID
                    schedule.setCreatedAt(new Date()); // 创建时间

                    // 插入中间表
                    int insertResult = trainingProgramCoursesScheduleService.insertTrainingProgramCoursesSchedule(schedule);
                    if (insertResult > 0) {
                        System.out.println("中间表插入成功：培养方案课程ID=" + tpcId + "，课程班ID=" + courseScheduleDetailsId);
                    } else {
                        System.out.println("警告：中间表插入失败：培养方案课程ID=" + tpcId + "，课程班ID=" + courseScheduleDetailsId);
                    }
                }
            }
            // ============================================================================

            // ===================== 修正：基于原始StudentInfo列表组装详细信息 =====================
            List<ClassWithStudentsVo> resultList = new ArrayList<>();
            for (CourseScheduleDetails classDetail : allCreatedClasses) {
                ClassWithStudentsVo vo = new ClassWithStudentsVo();
                vo.setClassInfo(classDetail);

                // 获取该班级对应的原始StudentInfo列表（保证ID正确）
                List<StudentInfo> originalStudents = classOriginalStudentsMap.getOrDefault(classDetail.getId(), Collections.emptyList());
                // 基于原始StudentInfo的ID获取详细信息
                List<studentDetailedVo> detailedStudents = originalStudents.stream()
                        .map(originalStudent -> studentInfoService.getStudentDetailedInfo(originalStudent.getId())) // 使用原始ID
                        .filter(Objects::nonNull) // 过滤空值
                        .collect(Collectors.toList());

                vo.setStudents(detailedStudents);
                resultList.add(vo);
                System.out.println("\n班级名称: " + classDetail.getClassName() +
                        ", 学生总数: " + detailedStudents.size() +
                        ", 原始学生ID列表: " + originalStudents.stream()
                        .map(StudentInfo::getId)
                        .collect(Collectors.joining(",")));
            }
            // ============================================================================

            System.out.println("-------------------------------------------");
            System.out.println("分班结果: " + resultList);
            System.out.println("-------------------------------------------");

            return AjaxResult.success("班级划分成功", resultList);

        } catch (Exception e) {
            logger.error("班级划分失败", e);
            return AjaxResult.error("班级划分失败: " + e.getMessage());
        }
    }

    // 添加辅助方法
    private int getIntegerValue(Map<String, Object> map, String key, int defaultValue) {
        Object value = map.get(key);
        if (value instanceof Integer) {
            return (Integer) value;
        } else if (value != null) {
            try {
                return Integer.parseInt(value.toString());
            } catch (NumberFormatException e) {
                return defaultValue;
            }
        }
        return defaultValue;
    }

    private Long getLongValue(Map<String, Object> map, String key, Long defaultValue) {
        Object value = map.get(key);
        if (value instanceof Long) {
            return (Long) value;
        } else if (value instanceof Integer) {
            return ((Integer) value).longValue();
        } else if (value != null) {
            try {
                return Long.parseLong(value.toString());
            } catch (NumberFormatException e) {
                return defaultValue;
            }
        }
        return defaultValue;
    }
    private String getStringValue(Map<String, Object> map, String key) {
        return getStringValue(map, key, null);
    }

    private String getStringValue(Map<String, Object> map, String key, String defaultValue) {
        Object value = map.get(key);
        if (value instanceof String) {
            return (String) value;
        } else if (value != null) {
            return value.toString();
        }
        return defaultValue;
    }
    /**
     * 删除学生信息管理
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:deleteAll')")
    @Log(title = "学生信息管理", businessType = BusinessType.DELETE)
    @DeleteMapping("/clearAll")
    public AjaxResult clearAll()
    {
        studentInfoService.clearAll();
        return AjaxResult.success("批量删除成功");
    }

    // 通过课程ID、学期ID和年级查询课程排课信息以及学生名单（包含详细信息）
    @GetMapping("/getCourseScheduleDetailsAndStudentList")
    public AjaxResult getCourseScheduleDetailsAndStudentList(
            @RequestParam("courseId") String courseId,
            @RequestParam("semesterId") int semesterId,
            @RequestParam("grade") int grade) {
        // 打印传入参数
        System.out.println("查询参数：课程ID=" + courseId + ", 学期ID=" + semesterId + ", 年级=" + grade);

        // 1. 查询所有符合条件的课程班信息
        List<CourseScheduleDetails> courseScheduleDetailsList =
                courseScheduleDetailsService.selectByCourseSemesterGrade(courseId, semesterId, grade);

        // 2. 构建返回结果：每个课程班包含其详细学生名单
        List<CourseAndStudentsDetailsVo> result = new ArrayList<>();
        for (CourseScheduleDetails courseSchedule : courseScheduleDetailsList) {
            // 3. 查询该课程班的学生关联记录
            List<CourseStudentInfo> studentRelations =
                    courseStudentInfoService.selectByCourseScheduleDetailsId(courseSchedule.getId());
            System.out.println("查询结果：" + studentRelations);
            // 4. 转换为详细学生信息列表
            List<studentDetailedVo> detailedStudents = new ArrayList<>();
            for (CourseStudentInfo relation : studentRelations) {
                try {
                    // 通过学生ID查询详细信息
                    studentDetailedVo studentDetail = studentInfoService.getStudentDetailedInfo(relation.getStudentId());
                    System.out.println("--------------：");
                    System.out.println("查询结果学生11111--------------：" + studentDetail);
                    System.out.println("--------------：");
                    if (studentDetail != null) {
                        detailedStudents.add(studentDetail);
                    } else {
                        System.out.println("警告：未查询到学生详细信息，学生ID=" + relation.getStudentId());
                    }
                } catch (Exception e) {
                    System.err.println("查询学生详细信息失败，学生ID=" + relation.getStudentId() + "，错误：" + e.getMessage());
                }
            }
            // 5. 封装课程班信息和详细学生名单
            CourseAndStudentsDetailsVo scheduleWithStudents = new CourseAndStudentsDetailsVo();
            scheduleWithStudents.setCourseScheduleDetails(courseSchedule);
            scheduleWithStudents.setStudentDetailedVo(detailedStudents); // 替换为详细信息列表
            //打印详细的学生信息
            System.out.println("封装结果1：" + detailedStudents);
            System.out.println("封装结果2：" + courseSchedule);
            System.out.println("封装结果3：" + scheduleWithStudents);
            result.add(scheduleWithStudents);
        }

        System.out.println("查询完成，共返回" + result.size() + "个课程班信息");
        return AjaxResult.success(result);
    }
    /*根据培养方案id列表查询对应的学生名单（返回详细信息）*/
    @PreAuthorize("@ss.hasPermi('student:studentManger:list')")
    @GetMapping("/selectStudentInfoListByTrainingProgramIds")
// 后端改为接收字符串，再手动分割为列表
    public AjaxResult selectStudentInfoListByTrainingProgramIds(
            @RequestParam(value = "trainingProgramIds", required = false) String trainingProgramIds) { // 改为String接收

        // 打印原始参数，确认是否收到
        System.out.println("------------接收的培养方案ID字符串：" + trainingProgramIds);

        try {
            // 1. 参数处理：字符串转列表（关键步骤）
            List<String> idsList = new ArrayList<>();
            if (trainingProgramIds != null && !trainingProgramIds.trim().isEmpty()) {
                // 按逗号分割字符串为列表（如 "id1,id2" → ["id1","id2"]）
                idsList = Arrays.stream(trainingProgramIds.split(","))
                        .map(String::trim) // 去除空格
                        .filter(id -> !id.isEmpty()) // 过滤空值
                        .collect(Collectors.toList());
            }

            // 后续逻辑不变（使用idsList处理）
            if (idsList.isEmpty()) {
                return AjaxResult.success(Collections.emptyList());
            }

            // 2. 调用服务层查询（用分割后的idsList）
            List<StudentInfo> students = studentInfoService.selectStudentInfoListByTrainingProgramIds(idsList);
            System.out.println("基础学生列表数量：" + students.size());

            // 3. 转换为详细信息列表（保持不变）
            List<studentDetailedVo> detailedStudents = students.stream()
                    .map(student -> {
                        try {
                            studentDetailedVo detail = studentInfoService.getStudentDetailedInfo(student.getId());
                            if (detail == null) {
                                System.out.println("警告：未查询到学生详细信息，学生ID=" + student.getId());
                            }
                            return detail;
                        } catch (Exception e) {
                            System.err.println("获取学生详细信息失败，学生ID=" + student.getId() + "，错误：" + e.getMessage());
                            return null;
                        }
                    })
                    .filter(Objects::nonNull)
                    .collect(Collectors.toList());
            System.out.println("转换后详细学生列表数量：" + detailedStudents.size());
            // 4. 打印转换后的学生详情
            System.out.println("===== 转换后详细学生列表详情（共" + detailedStudents.size() + "人） =====");
            for (int i = 0; i < detailedStudents.size(); i++) {
                studentDetailedVo student = detailedStudents.get(i);
                // 打印关键信息（根据实际属性调整）
                System.out.printf(
                        "学生%d：ID=%s, 学号=%s, 姓名=%s, 学院=%s, 专业=%s, 培养方案ID=%s%n",
                        i + 1,
                        student.getId(),                  // 学生ID
                        student.getStudentId(),           // 学号
                        student.getStudentName(),         // 姓名
                        student.getCollegeName(),         // 学院名称
                        student.getMajorName(),           // 专业名称
                        student.getTrainingProgramName()    // 所属培养方案ID
                );
            }
            System.out.println("==========================================");
            return AjaxResult.success(detailedStudents);
        } catch (Exception e) {
            logger.error("根据培养方案ID查询学生列表失败", e);
            return AjaxResult.error("查询失败：" + e.getMessage());
        }
    }
    /*
     * 根据传入的培养方案ID，返回对应的学生列表
     */
    @GetMapping("/listByTrainingProgram")
    public AjaxResult listStudentsByTrainingProgramId(String trainingProgramId) {
        System.out.println("传入的培养方案ID：" + trainingProgramId);
        return AjaxResult.success(studentInfoService.selectStudentInfoListByTrainingProgramIdAndSubject(trainingProgramId));
    }

    /*
     * 根据学生学号stduentId查询学生详细信息
     * */
    @GetMapping("/getStudentInfoByStudentId/{studentId}")
    public AjaxResult getStudentInfoByStudentId(@PathVariable("studentId") String studentId) {
        return AjaxResult.success(studentInfoService.getStudentReVoByStudentId(studentId));
    }
    @GetMapping("/getStudentInfoByStudentXh/{studentId}")
    public AjaxResult getStudentInfoByStudentXh(@PathVariable("studentId") String studentId) {
        return AjaxResult.success(studentInfoService.getStudentByStudentId(studentId));
    }
    /**
     * 生成导入批次号
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
    @GetMapping("/generateImportBatchNo")
    public AjaxResult generateImportBatchNo() {
        String batchNo = studentTutorImportService.generateBatchNo();
        return AjaxResult.success("批次号生成成功", batchNo);
    }

    /**
     * 导入学生导师关系
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
    @Log(title = "学生导师指定", businessType = BusinessType.IMPORT)
    @PostMapping("/importTutor")
    public AjaxResult importTutor(@RequestParam("file") MultipartFile file, @RequestParam("batchNo") String batchNo) {
        if (file.isEmpty()) {
            return AjaxResult.error("请选择Excel文件");
        }
        if (!file.getOriginalFilename().endsWith(".xlsx") && !file.getOriginalFilename().endsWith(".xls")) {
            return AjaxResult.error("仅支持Excel格式文件（.xlsx/.xls）");
        }

        studentTutorImportService.doImport(file, batchNo);
        return AjaxResult.success("导入任务已启动，可通过批次号查询进度", batchNo);
    }

    /**
     * 查询导入进度
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
    @GetMapping("/queryImportProgress/{batchNo}")
    public AjaxResult queryImportProgress(@PathVariable("batchNo") String batchNo) {
        return AjaxResult.success(studentTutorImportService.getImportProgress(batchNo));
    }

    /**
     * 下载失败数据
     */
    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
    @GetMapping("/downloadFailureData/{batchNo}")
    public void downloadFailureData(@PathVariable("batchNo") String batchNo, HttpServletResponse response) {
        try {
            studentTutorImportService.downloadFailureData(batchNo, response);
        } catch (IOException e) {
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
        }
    }

//    /**
//     * 下载导入模板
//     */
//    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
//    @PostMapping("/downloadTutorTemplate")
//    public void downloadTutorTemplate(HttpServletResponse response) {
//        try {
//            studentTutorImportService.downloadTemplate(response);
//        } catch (IOException e) {
//            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
//        }
//    }
       /**
        * 下载导入模板
        */
    @PreAuthorize("@ss.hasPermi('student:studentManger:importTutor')")
    @PostMapping("/downloadTutorTemplate")
    public void downloadTutorTemplate(HttpServletResponse response) {
        ExcelUtil<studentDaoShiVO> util = new ExcelUtil<>(studentDaoShiVO.class);
        util.importTemplateExcel(response,  "学生导师指定导入模板");
    }

    /**
     * 通过培养方案id获取对应课表
     */
    @GetMapping("/getCourseScheduleByTrainingProgramId/{trainingProgramId}")
    public AjaxResult getCourseScheduleByTrainingProgramId(@PathVariable("trainingProgramId") String trainingProgramId) {
        //打印获取到的培养方案ID
        System.out.println("传入的培养方案ID：" + trainingProgramId);
        List<CourseSchedulingIinquiryVo> courseScheduleDetails = courseSchedulingIinquiryService.selectCourseSchedulingIinquiryList(trainingProgramId);
        return AjaxResult.success(courseScheduleDetails);
    }

    /**通过课程班id获取学生名单，然后查询学生对应的已开课班级以及时间*/
    @GetMapping("/getStudentAndClassByClassId/{classId}")
    public AjaxResult getStudentAndClassByClassId(@PathVariable("classId") String classId){
        List<CourseSchedulingIinquiryVo> courseScheduleDetails = courseSchedulingIinquiryService.selectCourseSchedulingIinquiryListByClassId(classId);
        return AjaxResult.success(courseScheduleDetails);
    }
    /**根据学生ID获取对应课表*/
    //   @RequestMapping(value = "\"/getCourseScheduleByStudentId}\"", method = RequestMethod.GET)
    @GetMapping("/getCourseScheduleByStudentId")
    public AjaxResult getCourseScheduleByStudentId(){
        // 获取当前登录用户
        LoginUser user = SecurityUtils.getLoginUser();
        if (user == null) {
            return AjaxResult.error("未获取到登录用户信息");
        }

        // 根据用户名获取学生信息 - 这里应该是按 student_id 查询
        StudentInfo studentInfo = studentInfoServiceImpl.selectStudentInfoByStudentId(user.getUsername());

        System.out.println("查询条件: " + user.getUsername());
        System.out.println("查询结果: " + studentInfo);

        if (studentInfo == null) {
            return AjaxResult.error("未找到对应的学生信息");
        }

        // 使用学生ID查询课程安排
        List<CourseSchedulingIinquiryVo> courseScheduleDetails =
                courseSchedulingIinquiryService.selectCourseSchedulingIinquiryListByStudentId(studentInfo.getId());

        return AjaxResult.success(courseScheduleDetails);
    }
    @GetMapping("/listVo")
    public TableDataInfo listVo(StudentInfoVo studentInfoVo)
    {
        startPage();
        List<StudentInfoVo> list = studentInfoService.selectStudentInfoVoList(studentInfoVo);
        return getDataTable(list);
    }


}
